﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EasyPiano
{
    public partial class MusicScoreManagerForm : Form
    {
        public Song song;

        List<MusicScoreControl> musicScoreControls = new List<MusicScoreControl>();
        Thread listenThread;
        bool isPause = true;
        bool isDestory = false;
        int selectedLabelIndex = -1;
        int progress = 0;

        public MusicScoreManagerForm()
        {
            InitializeComponent();

            listenThread = new Thread(new ThreadStart(() =>
            {
                while (isDestory == false)
                {
                    if (isPause)
                        continue;
                    int single = (int)(nud_unitTime.Value);
                    while (progress < song.hand1.Count)
                    {
                        if (progress == -1)
                            progress = 0;

                        if (progress > 0)
                            musicScoreControls[progress - 1].CancelSelect();
                        musicScoreControls[progress].Playing();

                        int index1 = song.hand1[progress].soundIndex + song.offsetIndex;
                        if (song.hand1[progress].soundIndex > 0)
                            Util.AsynPlaySound(GlobalData.soundsPath[index1]);

                        if (song.HandCount == 2)
                        {
                            int index2 = song.hand2[progress].soundIndex + song.offsetIndex;
                            if (song.hand2[progress].soundIndex > 0)
                                Util.AsynPlaySound(GlobalData.soundsPath[index2]);
                        }

                        Thread.Sleep((int)(song.hand1[progress].duration * single));

                        progress++;

                        if (isPause)
                        {
                            break;
                        }
                    }

                    if (isPause == false)//播放完毕
                    {
                        progress = 0;
                        if (song.hand1.Count > 0)
                            musicScoreControls[song.hand1.Count - 1].CancelSelect();
                        isPause = true;
                    }
                }
            }));
            listenThread.IsBackground = false; 
            listenThread.Start();
        }

        private void MusicScoreControl_Click(object sender, EventArgs e)
        {
            CancelSelectedLabel();
            SelectLabel((MusicScoreControl)sender);
        }

        private MusicScoreControl GenerateMusicControl(string text1, string text2, float delay, string word)
        {
            MusicScoreControl msControl = new MusicScoreControl();
            if (song.HandCount == 2)
                msControl.IsTwoScore = true;
            msControl.HasWord = song.HasWord;

            msControl.SoundStr1 = text1;
            if (msControl.IsTwoScore)
                msControl.SoundStr2 = text2;
            if (msControl.HasWord)
                msControl.Word = word;
            msControl.Delay = (int)delay;

            msControl.Click += new EventHandler(MusicScoreControl_Click);
            
            return msControl;
        }
        private void SetMusicControl(MusicScoreControl target, string text1, string text2, float delay, string word)
        {
            if (song.HandCount == 2)
                target.IsTwoScore = true;
            target.HasWord = song.HasWord;

            target.SoundStr1 = text1;
            if (target.IsTwoScore)
                target.SoundStr2 = text2;
            if (target.HasWord)
                target.Word = word;
            target.Delay = (int)delay;                    
        }
        private void AddLabelToUI(string text1, string text2, float delay, string word)
        {
            MusicScoreControl msControl = GenerateMusicControl(text1, text2, delay, word);
            
            musicScoreControls.Add(msControl);
            flp_music.Controls.Add(msControl);
        }
        private void InsertLabelToUI(string text1, string text2, float delay, string word, int pos)
        {
            MusicScoreControl msControl = GenerateMusicControl(text1, text2, delay, word);

            //优化的插入
            musicScoreControls.Insert(pos, msControl);
            flp_music.Controls.Add(msControl);
            flp_music.Controls.SetChildIndex(msControl, pos);
        }     
        private void ChangeLabelToUI(string text1, string text2, float delay, string word)
        {
            //TODO bug
            if (selectedLabelIndex != -1)
            {
                MusicScoreControl msControl = musicScoreControls[selectedLabelIndex];
                SetMusicControl(msControl, text1, text2, delay, word);
            }
        }
        private void RemoveLabelFromUI(MusicScoreControl msControl)
        {
            if (msControl != null)
            {
                flp_music.Controls.Remove(msControl);
                musicScoreControls.Remove(msControl);
                msControl.Dispose();
            }
        }

        private void CancelSelectedLabel()
        {
            if (selectedLabelIndex != -1)
            {
                musicScoreControls[selectedLabelIndex].CancelSelect();
                selectedLabelIndex = -1;
                bt_change.Enabled = false;
                bt_delete.Enabled = false;
                bt_insert.Enabled = false;
            }
        }
        private void SelectLabel(MusicScoreControl msControl)
        {
            msControl.Selected();
            selectedLabelIndex = musicScoreControls.IndexOf(msControl);
            if (selectedLabelIndex != -1)
            {
                bt_change.Enabled = true;
                bt_delete.Enabled = true;
                bt_insert.Enabled = true;
                ss_target1.musicSoreText = song.hand1[selectedLabelIndex].ScoreString;
                if (song.HandCount == 2)
                    ss_target2.musicSoreText = song.hand2[selectedLabelIndex].ScoreString;
                if (song.HasWord)
                    tb_word.Text = song.words[selectedLabelIndex];
                tb_delay.Text = song.hand1[selectedLabelIndex].duration.ToString();
            }
        }


        private void bt_add_Click(object sender, EventArgs e)
        {
            try
            {
                int index1 = ss_target1.SelectedIndex;
                int index2 = ss_target2.SelectedIndex;
                float delay = float.Parse(tb_delay.Text);
                string word = tb_word.Text;
                
                song.Add(index1, index2, delay, word);
                AddLabelToUI(Util.SoundIndexToString(index1), Util.SoundIndexToString(index2), delay, word);
                CancelSelectedLabel();
            }
            catch
            {
                MessageBox.Show("数据有误，请检查数据合法性！", "提示");
            }           
        }

        private void MusicScoreManagerForm_Load(object sender, EventArgs e)
        {
            if (song == null)
            {
                song = new Song();
            }
            else
            {
                string soundStr1 = "";
                string soundStr2 = "";
                float delay = 1;
                string word = "";
                //to-do bug
                
                for (int i = 0; i < song.hand1.Count; i++)
                {
                    soundStr1 = song.hand1[i].ScoreString;
                    delay = song.hand1[i].duration;

                    if (song.HandCount == 2)
                    {
                        soundStr2 = song.hand2[i].ScoreString;
                    }

                    if(song.HasWord)
                    {
                        word = song.words[i];
                    }

                    AddLabelToUI(soundStr1, soundStr2, delay, word);
                }
            }

            tb_songName.Text = song.songName;
            tb_wordAuthor.Text = song.wordAuthor;
            tb_musicAuthor.Text = song.musicAuthor;
            nud_unitTime.Value = song.unitTime;
            cb_offset.SelectedIndex = song.offsetIndex;
            cb_handMode.SelectedIndex = song.HandCount - 1;
            cb_pai.SelectedIndex = 2;
            cb_show_word.SelectedIndex = song.HasWord ? 1 : 0;
        }

        private void bt_listen_Click(object sender, EventArgs e)
        {
            if (musicScoreControls.Count > 0)
            {
                if (progress >= 0)
                {
                    if (isPause && progress > 0)
                        musicScoreControls[progress - 1].CancelSelect();
                    else
                        musicScoreControls[progress].CancelSelect();
                    isPause = false;
                    progress = -1;
                    CancelSelectedLabel();
                }                
            }           
        }


        private void bt_save_Click(object sender, EventArgs e)
        {
            if (sfd_save_music_score.ShowDialog() == DialogResult.OK)
            {
                string file = sfd_save_music_score.FileName;
                song.songName = tb_songName.Text;
                song.wordAuthor = tb_wordAuthor.Text;
                song.musicAuthor = tb_musicAuthor.Text;
                song.unitTime = (int)(nud_unitTime.Value);
                song.offsetIndex = cb_offset.SelectedIndex;
                song.Save(file);
            }
        }

        private void bt_change_Click(object sender, EventArgs e)
        {
            try
            {
                if (selectedLabelIndex != -1)
                {
                    int index1 = ss_target1.SelectedIndex;
                    int index2 = ss_target2.SelectedIndex;
                    float delay = float.Parse(tb_delay.Text);
                    string word = tb_word.Text;

                    song.Change(selectedLabelIndex, index1, index2, delay, word);
                    ChangeLabelToUI(Util.SoundIndexToString(index1), Util.SoundIndexToString(index2), delay, word);                        
                    CancelSelectedLabel();
                }
            }
            catch
            {
                MessageBox.Show("数据有误，请检查数据合法性！", "提示");
            }            
        }

        private void bt_delete_Click(object sender, EventArgs e)
        {
            if (selectedLabelIndex != -1)
            {
                MusicScoreControl msControl = musicScoreControls[selectedLabelIndex];
                song.Remove(selectedLabelIndex);
                CancelSelectedLabel();
                RemoveLabelFromUI(msControl);
            }
        }

        private void bt_stop_Click(object sender, EventArgs e)
        {
            isPause = true;
        }

        private void bt_resume_Click(object sender, EventArgs e)
        {
            isPause = false;
        }

        private void MusicScoreManagerForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            isPause = true;
            isDestory = true;
        }

        private void bt_insert_Click(object sender, EventArgs e)
        {
            try
            {
                if (selectedLabelIndex != -1)
                {
                    int index1 = ss_target1.SelectedIndex;
                    int index2 = ss_target2.SelectedIndex;
                    string word = tb_word.Text;
                    float delay = float.Parse(tb_delay.Text);

                    song.Insert(selectedLabelIndex, index1, index2, delay, word);
                    InsertLabelToUI(Util.SoundIndexToString(index1), Util.SoundIndexToString(index2), delay, word, selectedLabelIndex);
                }
            }
            catch
            {
                MessageBox.Show("数据有误，请检查数据合法性！", "提示");
            }            
        }

        private void bt_small_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < song.hand1.Count; i++)
            {
                song.hand1[i].duration /= 2;
                if (song.HandCount == 2)
                    song.hand2[i].duration /= 2;
            }
            foreach (var item in musicScoreControls)
            {
                item.Width /= 2;
            }
        }

        private void bt_jump_Click(object sender, EventArgs e)
        {
            if (selectedLabelIndex != -1)
            {
                if (isPause)
                {
                    if (progress > 0)
                        musicScoreControls[progress - 1].CancelSelect();
                    progress = selectedLabelIndex;
                }
                else
                {
                    musicScoreControls[progress].CancelSelect();
                    progress = selectedLabelIndex - 1;
                }
                isPause = false;
                CancelSelectedLabel();
            }
        }

        private void cb_offset_SelectedIndexChanged(object sender, EventArgs e)
        {
            song.offsetIndex = cb_offset.SelectedIndex;
        }

        private void bt_big_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < song.hand1.Count; i++)
            {
                song.hand1[i].duration *= 2;
                if (song.HandCount == 2)
                    song.hand2[i].duration *= 2;
            }
            foreach (var item in musicScoreControls)
            {
                item.Width *= 2;
            }
        }

        void ChangeHandMode(WaitingForm form)
        {
            if (song.HandCount != cb_handMode.SelectedIndex + 1)
                song.HandCount = cb_handMode.SelectedIndex + 1;

            bool isTwoScore = song.HandCount == 2 ? true : false;

            ss_target2.Enabled = isTwoScore;

            foreach (var item in musicScoreControls)
            {
                item.IsTwoScore = isTwoScore;
                if (form != null)
                    form.progress++;
            }
        }
        private void cb_hand_mode_SelectedIndexChanged(object sender, EventArgs e)
        {            
            WaitingForm.ShowForm("正在切换弹奏模式...", musicScoreControls.Count, ChangeHandMode, this);
        }

        private void cb_pai_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = cb_pai.SelectedIndex;
            if (index != -1 && index != 5)
            {
                string text = (Math.Pow(2, 2 - index) * 4).ToString();
                if (tb_delay.Text != text)
                {
                    tb_delay.Text = text;
                }
            }
        }

        private void tb_delay_TextChanged(object sender, EventArgs e)
        {
            try
            {
                double delay = double.Parse(tb_delay.Text);
                double index = 2 - Math.Log(delay / 4, 2);
                if (Math.Abs(index - (int)index) < 1e-6)
                {
                    if (cb_pai.SelectedIndex != (int)index)
                        cb_pai.SelectedIndex = (int)index;
                }
                else
                {
                    cb_pai.SelectedIndex = 5;
                }
            }
            catch
            {

            }                     
        }
        void ChangeShowWords(WaitingForm form)
        {
            bool hasWord = false;
            if (cb_show_word.SelectedIndex == 1)
                hasWord = true;

            if (song.HasWord != hasWord)
                song.HasWord = hasWord;

            tb_word.Enabled = hasWord;

            foreach (var item in musicScoreControls)
            {
                item.HasWord = hasWord;
                if (form != null)
                    form.progress++;
            }
        }
        private void cb_show_word_SelectedIndexChanged(object sender, EventArgs e)
        {
            WaitingForm.ShowForm("正在切换歌词的显示方式...", musicScoreControls.Count, ChangeShowWords, this);
        }
    }
}
